﻿using System;
using System.Reflection;
using System.Collections;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
using System.Data.Entity;
using System.Data.OleDb;
using System.Text;
using System.Collections.Generic;
using FL.DAL;

namespace FL.DBModule
{
    /// <summary>
    /// 说明：实体基类
    /// </summary>
    [Serializable]
    public class BaseEntity 
    {
        private BaseEntityDataContext dbContext;
        private BaseEntityDataContext DBContext
        {
            get
            {
                if (dbContext == null)
                {
                    dbContext = new BaseEntityDataContext();
                }
               return dbContext;
            }
            set
            {
                if (value == null)
                {
                    dbContext = new BaseEntityDataContext();
                }
                else
                {
                    dbContext = value;
                }
            }
        }


        /// <summary>
        /// 數據複製，把自身複製一份。
        /// </summary>
        /// <returns>返回被複製的對象</returns>
        public virtual BaseEntity Clone()
        {
            Type theType = this.GetType();
            BaseEntity Result = (BaseEntity)Activator.CreateInstance(theType);
            PropertyInfo[] Mypropertyinfos =  this.GetType().GetProperties();
            foreach(PropertyInfo proInfo in Mypropertyinfos)
            {   
                PropertyInfo prop = theType.GetProperty(proInfo.Name);
                if (prop == null)
                    continue;
                if (prop.CanWrite && prop.CanRead)
                {
                    object value1 = prop.GetValue(this, null);
                    if (value1 != null)
                    {
                        if (prop.PropertyType.GetInterface(typeof(ICollection).ToString(), true) == null)
                        {
                            object temp = this;
                            //member.StorageAccessor.SetBoxedValue(ref temp, value1);
                            prop.SetValue(Result, value1, null);
                        }
                    }
                }
            }
            return Result;
        }

        public static IList<T> GetList<T>(string tablename, string condition) where T : BaseEntity
        {
            DAL.DbSql db = new DAL.DbSql();
            string strSql = "select * from " + tablename + " where " + condition;
            DataTable dt = db.ExecuteQuery(strSql);
            return DatatableToObject<T>(dt);
        }


         //<summary>
         //获取外键信息
         //</summary>
         //<param name="Table">表名</param>
         //<returns></returns>
        public IList<SysTableFKey> GetFKey(string Table)
        {
            string strSql = string.Format(@"select t1.name as FieldName, t2.rtableName as FKTableName,
            t2.name as FKFieldName from (select col.name, f.constid as temp  from syscolumns col,sysforeignkeys f  where f.fkeyid=col.id  and f.fkey=col.colid  and f.constid in  
            ( select distinct(id)     from sysobjects    where OBJECT_NAME(parent_obj)='{0}'
                and xtype='F'   )  ) as t1 , (
            select OBJECT_NAME(f.rkeyid) as rtableName,col.name, f.constid as temp  from 
            syscolumns col,sysforeignkeys f  
            where f.rkeyid=col.id  and f.rkey=col.colid  
            and f.constid in  ( select distinct(id)    from sysobjects   
             where OBJECT_NAME(parent_obj)='{0}'    and xtype='F'  ) )
             as t2 where t1.temp=t2.temp", Table);
            DAL.DbSql db = new DAL.DbSql();
            DataTable dt = db.ExecuteQuery(strSql);
            return DatatableToObject<SysTableFKey>(dt);      
        }

        public IList<SysTableFKey> GetFKey2(string Table)
        {
            // SysMasterDetailRelation 用于定义主表和从表的主外键关联关系
            string strSql = string.Format(@"select FieldName, FKTableName, FKFieldName 
                                                from dbo.SysMasterDetailRelation 
                                                where ObjectName='{0}'", Table);
            DAL.DbSql db = new DAL.DbSql();
            DataTable dt = db.ExecuteQuery(strSql);
            return DatatableToObject<SysTableFKey>(dt);
        }

        public IList<SysTableFKey> GetFKey()
        {
            IList<SysTableFKey> fkList = GetFKey(this.GetTableName());

            if (fkList == null)
            {
                fkList = GetFKey2(this.GetTableName());
            }

            return fkList;     //GetFKey(this.GetTableName());
        }


        //public IList<BaseEntity> GetMasterChilds(string tablename, string condition)
        //{
        //    DAL.DbSql db = new DAL.DbSql();
        //    string strSql = "select * from " + tablename + " where " + condition;
        //    DataTable dt = db.ExecuteQuery(strSql);
        //    IList<BaseEntity> list = DatatableToObject(dt);
        //    IList<BaseEntity> _list = new List<BaseEntity>();
        //    foreach (BaseEntity t in list)
        //    {
        //        _list.Add(t as BaseEntity);
        //    }
        //    return _list;
        //}

        //public IList<BaseEntity> GetMasterChilds<T>(string tablename, string condition) where T : BaseEntity
        //{
        //    DAL.DbSql db = new DAL.DbSql();
        //    string strSql = "select * from " + tablename + " where " + condition;
        //    DataTable dt = db.ExecuteQuery(strSql);
        //    IList<T> list = DatatableToObject<T>(dt);
        //    IList<BaseEntity> _list = new List<BaseEntity>();
        //    foreach(T t in list)
        //    {
        //        _list.Add(t as BaseEntity);
        //    }
        //    return _list;
        //}


        public string GetDataCheckMessage()
        {
            return "";
        }

        //<summary>
         //通过查询结果，返回实体数组;
         //</summary>
         //<param name="dt">查询结果</param>
         //<returns>实体对象</returns>
        public static IList<T> DatatableToObject<T>(DataTable dt) where T:BaseEntity
        {
            if (dt.Rows.Count == 0)
            {
                return null;
            }
            Type t = Activator.CreateInstance<T>().GetType();
            PropertyInfo[] Mypropertyinfos = t.GetProperties();
            IList<T> al = new List<T>();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                T _obj = System.Reflection.Assembly.GetAssembly(t).CreateInstance(t.ToString()) as T;
                foreach (PropertyInfo pi in Mypropertyinfos)
                {
                    if (pi.Name.IndexOf("iSun_") == 0)
                        continue;
                    try
                    {
                        _obj.SetPropertyValue(pi.Name, dt.Rows[i].ItemArray[dt.Columns[pi.Name].Ordinal].ToString());
                        //FL.Common.Globals.SetPropertyValue(_obj, pi.Name, dt.Rows[i].ItemArray[dt.Columns[pi.Name].Ordinal].ToString());
                    }
                    catch (System.Exception e)
                    {
                        //log
                        //throw e;
                    }
                }
                al.Add(_obj);
            }
            return al;
        }

        public  void SetFieldValue(BaseEntity obj,string p,object v)
        {
            if (obj is DataTableBaseEntity)
            {
                ((DataTableBaseEntity)obj).SetValue(p, v);
            }
            else
            {
                obj.SetPropertyValue(p, v);
            }
        }
        /// <summary>
        /// 跟据类型名称,将DataTable转换成对象LIST
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="EntityName"></param>
        /// <returns></returns>
        public IList<BaseEntity> DatatableToObject(DataTable dt,string EntityName)
        {
            if (dt.Rows.Count == 0)
            {
                return null;
            }
            IList<FL.DBModule.Sys.t_sys_lib> list = GetList<FL.DBModule.Sys.t_sys_lib>("t_sys_lib", "type='e'");
            BaseEntity _entity = null;
            Type t = null;
            foreach(var en in list)
            {
                try
                {
                    t = Activator.CreateInstance(en.name + "." + EntityName, en.name).GetType();
                    _entity = System.Reflection.Assembly.GetAssembly(t).CreateInstance(t.ToString()) as BaseEntity;
                }
                catch { }
            }
  
            PropertyInfo[] Mypropertyinfos = t.GetProperties();
            IList<BaseEntity> al = new List<BaseEntity>();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                BaseEntity _obj = System.Reflection.Assembly.GetAssembly(t).CreateInstance(t.ToString()) as BaseEntity;
                foreach (PropertyInfo pi in Mypropertyinfos)
                {
                    if (pi.Name.IndexOf("iSun_") == 0)
                        continue;
                    try
                    {
                        _obj.SetPropertyValue(pi.Name, dt.Rows[i].ItemArray[dt.Columns[pi.Name].Ordinal].ToString());
                    }
                    catch (System.Exception e)
                    {
                   }
                }
                al.Add(_obj);
            }
            return al;
        }


        /// <summary>
        /// 数据置NULL
        /// </summary>
        /// <param name="AObject"></param>
        /// <param name="SetToNull"></param>
        public virtual void ClearData(BaseEntity AObject, bool SetToNull)
        {
            if (SetToNull)
            {
                AObject = null;
            }
        }

        /// <summary>
        /// 数据验证[]
        /// </summary>
        /// <returns>返回数据验证结果</returns>
        public virtual string CheckData()
        {
            return "";
        }


        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// 对象比较
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public bool Equals(BaseEntity obj)
        {
            if (!(obj is BaseEntity))
                return base.Equals(obj);

            if (obj.GetType() != this.GetType())
                return false;

            BaseEntity ASource = obj as BaseEntity;

            Type theType = this.GetType();

            object[] Attr = theType.GetCustomAttributes(typeof(TableAttribute), true);
            if (Attr.Length == 0)
                return false;
            PropertyInfo[] Mypropertyinfos = this.GetType().GetProperties();
            foreach (PropertyInfo proInfo in Mypropertyinfos)
            { 
                PropertyInfo prop = theType.GetProperty(proInfo.Name);

                Object Value1 = prop.GetValue(this, null);
                Object Value2 = prop.GetValue(ASource, null);
                if ((Value1 == null && Value2 != null) || (Value1 != null && Value2 == null))
                    return false;

                if (Value1 != null)
                {
                    if (!Value1.Equals(Value2))
                        return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 获取当前实体对应的表名
        /// </summary>
        /// <returns></returns>
        public string GetTableName()
        {
            var entity = (this as DataTableBaseEntity);
            if (entity != null)
            {
                return entity.TableName;
            }
            Type t = this.GetType();
            foreach (Attribute attr in t.GetCustomAttributes(true))
            {
                TableAttribute tableattribute = attr as TableAttribute;
                if (null != tableattribute)
                {
                    return tableattribute.TableName;
                }
            }
            return "";
        }

        /// <summary>
        /// 获取数据表的关键字段及其类型
        /// </summary>
        /// <returns></returns>
        public string[] GetKey()
        {
            object[] o = new object[1];
            o[0] = this;
            object instance = CreateInstance("FL.Bussiness.BaseBussnies", "FL.Bussiness", o);

            Type t = instance.GetType();
            object obj = t.InvokeMember("GetKey", BindingFlags.Default | BindingFlags.InvokeMethod
                        , null, instance, null);
            return obj as string[];
        }

        /// <summary>
        /// 获取当前实体对应关键字段
        /// </summary>
        /// <returns></returns>
        public virtual string GetTableKeyField()
        {
            Type t = this.GetType();
            var entity = (this as DataTableBaseEntity);
            if (entity != null)
            {
                /**/
                object[] o = new object[1];
                o[0] = this;
                object instance = CreateInstance("FL.Bussiness.BaseBussnies", "FL.Bussiness", o);

                t = instance.GetType();
                object obj = t.InvokeMember("GetKeyField", BindingFlags.Default | BindingFlags.InvokeMethod
                            , null, instance, null);
                //entity.TableKey = obj as string;
                return obj as string; 
            }
           
            foreach (Attribute attr in t.GetCustomAttributes(true))
            {
                TableAttribute tableattribute = attr as TableAttribute;
                if (null != tableattribute)
                {
                    return tableattribute.Guid;
                }
            }
            return "";

        }

        public virtual string GetTableIdValue()
        {
            var entity = (this as DataTableBaseEntity);
            if (entity != null)
            {
                if (((DataTableBaseEntity)entity).DRow[((DataTableBaseEntity)entity).KeyField] == null)
                {
                    return Guid.Empty.ToString();
                }
                return ((DataTableBaseEntity)entity).DRow[((DataTableBaseEntity)entity).KeyField].ToString();
            }
            Type t = this.GetType();
            string id = GetTableKeyField();
            PropertyInfo prop = t.GetProperty(id);
            object value1 = prop.GetValue(this, null);

            return Convert.ToString(value1);
        }


        /// <summary>
        /// 创建实例
        /// </summary>
        /// <param name="TypeName">类型名</param>
        /// <param name="AssemblyName">动态库命</param>
        /// <returns>实例对象</returns>
        public virtual object CreateInstance(string TypeName, string AssemblyName)
        {
            Assembly assem = Assembly.Load(AssemblyName);
            object obj = CreateInstance(TypeName, assem);
            return obj;
        }
        public  virtual object CreateInstance(string TypeName, string AssemblyName, object[] o)
        {
            Assembly assem = Assembly.Load(AssemblyName);
            object obj = CreateInstance(TypeName, assem, o);
            return obj;
        }
        /// <summary>
        /// 创建实例
        /// </summary>
        /// <param name="TypeName">类型名</param>
        /// <param name="assembly">动态库</param>
        /// <returns>实例对象</returns>
        public virtual object CreateInstance(string TypeName, Assembly assembly)
        {
            try
            {
                Type t = assembly.GetType(TypeName);
                if (t == null)
                {
                    t = assembly.GetType(assembly.GetName().Name + "." + TypeName);
                }
                object obj = Activator.CreateInstance(t);
                return obj;
            }
            catch (System.Exception e)
            {
                throw e;
            }

        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <param name="TypeName">类型名</param>
        /// <param name="assembly">动态库</param>
        /// <returns>实例对象</returns>
        public virtual object CreateInstance(string TypeName, Assembly assembly, object[] o)
        {
            try
            {
                Type t = assembly.GetType(TypeName);
                if (t == null)
                {
                    t = assembly.GetType(assembly.GetName().Name + "." + TypeName);
                }
                object obj = Activator.CreateInstance(t, o);
                return obj;
            }
            catch (System.Exception e)
            {
                throw e;
            }

        }
        /// <summary>
        /// 获取当前实体对应的自增ID或整型ID
        /// </summary>
        /// <returns></returns>
        public string GetTableIdentity()
        {
            Type t = this.GetType();
            foreach (Attribute attr in t.GetCustomAttributes(true))
            {
                TableAttribute tableattribute = attr as TableAttribute;
                if (null != tableattribute)
                {
                    return tableattribute.Identity;
                }
            }
            return "";
        }
        
 
        #region IComparable Members
        /// <summary>
        /// 数据比较
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int CompareTo(object obj)
        {
            if (obj == null)
                return -1;
            if (this.Equals(obj))
                return 0;

            return 1;
        }

        /// <summary>
        /// 获取默认值
        /// </summary>
        /// <param name="tablename">表</param>
        /// <returns></returns>
        public SortedDictionary<string, object> GetDefalutValueData(string tablename)
        {
            string strSql = string.Format(@"select ColName as field_name,VDefault as default_value from v_table_info_sturc where TableName='{0}' and (VDefault is not null and len(VDefault)>0)", tablename);
            DAL.DbSql db = new DAL.DbSql();
            DataTable dt = db.ExecuteQuery(strSql);
            SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
            foreach (DataRow row in dt.Rows)
            {
                dic.Add(row[0].ToString(), row[1]);
            }
            return dic;
        }


        #endregion
    }


    /// <summary>
    /// 
    /// </summary>
    public class BaseEntityDataContext
    {
        public BaseEntityDataContext(BaseEntity entity)
        {
            dbConnention = System.Configuration.ConfigurationManager.AppSettings["defualtConnString"];
            dbType = System.Configuration.ConfigurationManager.AppSettings["defualtDbType"];
            if (string.IsNullOrEmpty(dbType))
            {
                dbType = "SqlServer";
            }
        }

        public BaseEntityDataContext()
        {
            dbConnention = System.Configuration.ConfigurationManager.AppSettings["defualtConnString"];
            dbType = System.Configuration.ConfigurationManager.AppSettings["defualtDbType"];
            if (string.IsNullOrEmpty(dbType))
            {
                dbType = "SqlServer";
            }
        }

        public BaseEntityDataContext(string dbConnKey,string dbTypeKey)
        {
            dbConnention = System.Configuration.ConfigurationManager.AppSettings[dbConnKey];
            dbType = dbConnention = System.Configuration.ConfigurationManager.AppSettings[dbTypeKey];
            if (string.IsNullOrEmpty(dbType))
            {
                dbType = "SqlServer";
            }
        }

        private string dbConnention;
        public string DbConnention
        {
            get
            {
                return dbConnention;
            }
            set
            {
                if (value == null)
                {
                    dbConnention = System.Configuration.ConfigurationManager.AppSettings["defualtConnString"];
                }
                else
                {
                    dbConnention = value;
                }
            }
        }


        private string dbType;
        public string DbType
        {
            get
            {
                return dbType;
            }
            set
            {
                if (value == null)
                {
                    dbType = "SqlServer";
                }
                else
                {
                    dbType = value;
                }
            }
        }
    }
}
